<?php

namespace App\Service;

use App\Entity\Money;
use App\Entity\MoneyLogType;
use App\Entity\MoneyPayOrder;
use App\Entity\MoneyType;
use App\Entity\User;
use App\Repository\ConfigRepository;
use App\Repository\MoneyConfigRepository;
use App\Repository\MoneyLogRepository;
use App\Repository\MoneyLogTypeRepository;
use App\Repository\MoneyPayOrderRepository;
use App\Repository\MoneyRepository;
use App\Repository\MoneyStaticRepository;
use App\Repository\MoneyTypeRepository;
use App\Repository\UserRepository;
use App\Repository\Wuliu\WuliuUserLevelRepository;
use App\Repository\Wuliu\WuliuUserRepository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Request;

class PayService extends ServiceEntityRepository
{
    //支付参数设置
    const __PAY_TYPE_WECHAT__ = 100;
    const __PAY_TYPE_ALIPAY__ = 200;
    const __PAY_TYPE_UNION__ = 300;

    public $moneyService;
    public $orderService;
    public $userRepository;
    public $moneyRepository;
    public $moneyLogRepository;
    public $moneyTypeRepository;
    public $moneyConfigRepository;
    public $moneyStaticRepository;
    public $moneyLogTypeRepository;
    public $moneyPayOrderRepository;
    public $configRepository;
    public $wuliuUserRepository;
    public $wuliuUserLevelRepository;

    public function __construct(
        ManagerRegistry $registry
        , MoneyService $moneyService
        , UserRepository $userRepository
        , MoneyRepository $moneyRepository
        , MoneyLogRepository $moneyLogRepository
        , MoneyTypeRepository $moneyTypeRepository
        , MoneyConfigRepository $moneyConfigRepository
        , MoneyStaticRepository $moneyStaticRepository
        , MoneyLogTypeRepository $moneyLogTypeRepository
        , MoneyPayOrderRepository $moneyPayOrderRepository
        , ConfigRepository $configRepository
        , WuliuUserRepository $wuliuUserRepository
        , WuliuUserLevelRepository $wuliuUserLevelRepository
    )
    {
        parent::__construct($registry, Money::class);
        $this->moneyService = $moneyService;
        $this->userRepository = $userRepository;
        $this->moneyRepository = $moneyRepository;
        $this->moneyLogRepository = $moneyLogRepository;
        $this->moneyTypeRepository = $moneyTypeRepository;
        $this->moneyConfigRepository = $moneyConfigRepository;
        $this->moneyStaticRepository = $moneyStaticRepository;
        $this->moneyLogTypeRepository = $moneyLogTypeRepository;
        $this->moneyPayOrderRepository = $moneyPayOrderRepository;
        $this->configRepository = $configRepository;
        $this->wuliuUserRepository = $wuliuUserRepository;
        $this->wuliuUserLevelRepository = $wuliuUserLevelRepository;
    }

    /**
     * @param User $user
     * @param float $money
     * @param MoneyType|null $moneyType
     * @param null $param
     * @param MoneyLogType|null $logType
     * @param array $eventFlag
     * @return MoneyPayOrder
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function createPayOrder(User $user, float $money, MoneyType $moneyType = null, $param = null, MoneyLogType $logType = null,$eventFlag=[])
    {
        $order = new MoneyPayOrder();
        $order->setUser($user)
            ->setMoney($money)
            ->setCreateAt(new \DateTime())
            ->setPayAt(null)
            ->setSn(uniqid($user->getId()))//回调唯一码
            ->setData(null)//回调数据
            ->setLogType($logType)
            ->setMoneyType($moneyType)
            ->setEventFlag($eventFlag)
            ->setParam($param);
        $this->_em->persist($order);
        $this->_em->flush();
        return $order;
    }

    /**
     * 检查支付类型是否合法
     * @param $payType
     * @return bool
     */
    public function checkPayType($payType)
    {
        switch ($payType) {
            case self::__PAY_TYPE_WECHAT__:
                $payType = self::__PAY_TYPE_WECHAT__;
                break;
            case self::__PAY_TYPE_ALIPAY__:
                $payType = self::__PAY_TYPE_ALIPAY__;
                break;
            case self::__PAY_TYPE_UNION__:
                $payType = self::__PAY_TYPE_UNION__;
                break;
            default:
                return false;
        }
        return true;
    }

    public function dealWithCallBackUserCharge($sn)
    {
        $payOrder = $this->moneyPayOrderRepository->findOneBy(array("sn" => $sn));
        if ($payOrder->getPayAt()) {
            return false;//已经处理过了
        }
        $request = Request::createFromGlobals();
        $data = [
            "get" => $_GET
            , "post" => $_POST
            , "input" => file_get_contents('php://input')
            , "req_request" => $request->request->all()
            , "req_query" => $request->query->all()
            , "request" => $request
            , "error" => ""
        ];
        $this->_em->beginTransaction();
        try {
            $payOrder->setPayAt(new \DateTime())->setData($data);
            //修改订单支付信息
//            $this->moneyService->mod($payOrder->getUser(),$payOrder->getMoney(),MoneyService::__MONEY_XIAN_JIN__,101,"在线充值");
            $user = $payOrder->getUser();
            $wUser = $this->wuliuUserRepository->findOneBy(array("user" => $user));
            if (!$wUser) {
                $data["error"] = "未找到用户";
                $payOrder->setData($data);
                } else {
                $wUserLevelCur = $wUser->getLevel();
                $wLevels = $this->wuliuUserLevelRepository->findAll();
                foreach ($wLevels as $level) {
                    if ($level->getPrice() == $payOrder->getMoney()) {
                        //是否需要改变用户等级
                        if ($wUserLevelCur->getLevel() < $level->getLevel()) {
                            $wUser->setLevel($level);
                        }
                        //修改用户的会员期限
                        if ($wUser->getExpireAt()->getTimestamp() < time()) {
                            $time = time() + $level->getDays() * 24 * 3600;
                        }else{
                            $time = $wUser->getExpireAt()->getTimestamp() + $level->getDays() * 24 * 3600;
                        }
                        $wUser->setExpireAt(
                            new \DateTime(date(YYMMDDHHIISS, $time))
                        );
                        $this->_em->persist($wUser);

                    }
                }
            }
            $this->_em->persist($payOrder);
            $this->_em->flush();
        } catch (\Exception $exception) {
            $this->_em->rollback();
            throw $exception;
        }
        $this->_em->commit();
    }


    public function dealWithCallBackOrder($sn)
    {
        $payOrder = $this->moneyPayOrderRepository->findOneBy(array("sn" => $sn));
        if ($payOrder->getPayAt()) {
            return false;//已经处理过了
        }
        $request = Request::createFromGlobals();
        $data = [
            "get" => $_GET
            , "post" => $_POST
            , "input" => "php://input"
            , "req_request" => $request->request->all()
            , "req_query" => $request->query->all()
            , "request" => $request
        ];
        $this->_em->beginTransaction();
        try {
            //修改订单支付信息
            $payOrder->setPayAt(new \DateTime())->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();
            $param = $payOrder->getParam();
            $orderId = $param["orderId"];

            $rst = $this->orderService->dealWithOrderPay($orderId);
            if (!$rst) {

            }

        } catch (\Exception $exception) {
            $this->_em->rollback();
            $data["error"] = true;
            $payOrder->setData($data);
            $this->_em->persist($payOrder);
            $this->_em->flush();
            throw $exception;
        }
        $this->_em->commit();
    }


    public function uniCallBack($sn, $from = "")
    {
        switch ($from) {
            case "order":
                $this->dealWithCallBackOrder($sn);
                break;
            case "charge":
                $this->dealWithCallBackUserCharge($sn);
                break;
        }
    }


}